#include "sock.h"

#include <cstdio>

cpp_fds::cpp_fds(){
    zero();
}

int cpp_fds::fmax(){
    return maxval;
}
void cpp_fds::zero(){
    FD_ZERO(&inset);
    maxval = 0;
}
void cpp_fds::set(SOCKET sok){
    FD_SET(sok,&inset);
    if( sok > maxval ){
        maxval = sok;
    }
}
bool cpp_fds::isset(SOCKET sok){
    return FD_ISSET(sok,&inset);
}
void cpp_fds::end(){
    maxval++;
}
fd_set* cpp_fds::get(){
    return &inset;
}

cpp_socket::cpp_socket(cpp_socket* sk){
    sk->sock_trans(this);
}
cpp_socket::cpp_socket(SOCKET sk,SOCKADDR_IN si):   mySock( sk ),
                                                    myConf( si ),
                                                    opened( true ){}
cpp_socket::cpp_socket(int a,int b,int c):    mySock( socket(a,b,c) ),
                                              opened( false ){
}
cpp_socket::~cpp_socket(){
    if( opened ) closesocket( mySock );
}

bool cpp_socket::isValid(){
    return mySock != INVALID_SOCKET;
}

SOCKET cpp_socket::getSocket(){
    return mySock;
}
void cpp_socket::sock_trans(cpp_socket* sk){
    memcpy(sk,this,sizeof(cpp_socket));
    opened = false;
}

void cpp_socket::sin_family( short int sf ){
    myConf.sin_family = sf;
}
void cpp_socket::sin_port( unsigned short int prt){
    myConf.sin_port = htons( prt );
}
void cpp_socket::sin_addr( struct in_addr ia){
    myConf.sin_addr = ia;
}
void cpp_socket::sin_addr( unsigned long ia ){
    myConf.sin_addr.s_addr = ia;
}
void cpp_socket::sin_addr( char* address){
    myConf.sin_addr.s_addr = inet_addr(address);
}

bool cpp_socket::s_bind(){
    return !(opened = bind( mySock, (SOCKADDR*)&myConf, (size_t)sizeof(myConf)));
}
bool cpp_socket::s_listen(int queueSize){
    return !listen( mySock, queueSize);
}
cpp_socket* cpp_socket::s_accept(){
    SOCKET sock;
    SOCKADDR_IN sin;
    int sinsize = sizeof(sin);
    if((sock = accept( mySock, (SOCKADDR*)&sin, &sinsize)) == INVALID_SOCKET) return NULL;
    return new cpp_socket( sock, sin );
}
sockInfo* cpp_socket::s_getpeername(){
    SOCKADDR_IN sin;
    int sinsize = sizeof(sin);
    if( getpeername( mySock, (SOCKADDR*)&sin, &sinsize ) == -1) return NULL;
    return new sockInfo( sin );
}

int cpp_socket::s_recv(char* content,int len,unsigned int flags){
    return recv(mySock,content,len,flags);
}
int cpp_socket::s_send(char* content,int len,unsigned int flags){
    return send(mySock,content,len,flags);
}

sockInfo::sockInfo( SOCKADDR_IN sin ):  infos( sin ){
}
sockInfo::~sockInfo(){}
unsigned short sockInfo::port(){
    return ntohs( infos.sin_port );
}
const char* sockInfo::ip_address(){
    return inet_ntoa( infos.sin_addr );
}
